import {expect} from 'chai'
import sinon from 'sinon';
import {getRealGitTag} from '../src/tag'
import fs from 'fs'
import * as step from '@flow-step/step-toolkit'
import proxyquire from 'proxyquire'


describe('gitTag', () => {
    let envStub: sinon.SinonStub;
    let git: any;
    let simpleGitStub: sinon.SinonStub;
    let stepInfoStub: sinon.SinonStub;
    let stepErrorStub: sinon.SinonStub;
    const workDir = './workspace';
    const myRepo = 'my-repo_LBTL';
    const sources = JSON.stringify([
        {
            name: myRepo,
            data: {},
        },
    ]);
    let pathStub = {
        basename: sinon.stub().returns('my-repo_LBTL')
    };

    beforeEach(() => {
        envStub = sinon.stub(process, 'env')
        stepInfoStub = sinon.stub(step, 'info');
        stepErrorStub = sinon.stub(step, 'error');
        git = {
            addConfig: sinon.stub().resolves(),
            env: sinon.stub().resolves(),
            cwd: sinon.stub().resolves(),
            tag: sinon.stub().resolves(),
            push: sinon.stub().resolves()
        }
        simpleGitStub = sinon.stub().returns(git);
    });

    afterEach(() => {
        sinon.restore();
    });

    it('should create and push a git tag with a message', async () => {
        envStub.value({
            'SOURCES': sources,
            'GIT_TAG': '${BUILD_NUMBER}_07_24',
            'BUILD_NUMBER': '225',
            'GIT_TAG_MSG': 'test-msg'});

        const gitTagProxy = proxyquire('../src/tag', {
            path: pathStub,
            'simple-git': {simpleGit: simpleGitStub},
        }).gitTag;

        await gitTagProxy();

        const expectedTag = '225_07_24';
        const expectedMsg = 'test-msg';
        expect(git.tag.calledWithExactly(['-f', expectedTag, '-m', expectedMsg])).to.be.true;
        expect(stepInfoStub.calledWithExactly(`git tag ${expectedTag} with message ${expectedMsg}`)).to.be.true;
        expect(git.push.calledOnceWith(['origin', expectedTag])).to.be.true;
        expect(stepInfoStub.calledWithExactly(`git push origin tag ${expectedTag} succeeded`)).to.be.true;
    })

    it('should create and push a git tag without a message', async () => {
        envStub.value({
            'SOURCES': sources,
            'GIT_TAG': '${BUILD_NUMBER}_07_24',
            'BUILD_NUMBER': '225',
        });
        const gitTagProxy = proxyquire('../src/tag', {
            path: pathStub,
            'simple-git': {simpleGit: simpleGitStub},
        }).gitTag;

        await gitTagProxy();

        const expectedTag = '225_07_24';
        expect(git.tag.calledWithExactly(['-f', expectedTag])).to.be.true;
        expect(stepInfoStub.calledWithExactly(`git tag ${expectedTag}`)).to.be.true;
        expect(git.push.calledOnceWith(['origin', expectedTag])).to.be.true;
        expect(stepInfoStub.calledWithExactly(`git push origin tag ${expectedTag} succeeded`)).to.be.true;
    })

    it('should fail if the repository does not exist', async () => {
        git.push.rejects(new Error('repository not found'));
        envStub.value({
            'SOURCES': sources,
            'GIT_TAG': '${BUILD_NUMBER}_07_24',
            'BUILD_NUMBER': '225',
        });
        const gitTagProxy = proxyquire('../src/tag', {
            path: pathStub,
            'simple-git': {simpleGit: simpleGitStub},
        }).gitTag;

        try {
            await gitTagProxy();
        } catch (error:any) {
            expect(error.message).to.equal('repository not found');
            expect(stepErrorStub.calledWith('repository does not exist, or the user has no permission')).to.be.true;
            expect(stepErrorStub.calledWith('git push origin tag 225_07_24 failed')).to.be.true;
        }
    })

    it('should handle other push errors', async function () {
        git.push.rejects(new Error('some other error'));
        envStub.value({
            'SOURCES': sources,
            'GIT_TAG': '${BUILD_NUMBER}_07_24',
            'BUILD_NUMBER': '225',
        });
        const gitTagProxy = proxyquire('../src/tag', {
            path: pathStub,
            'simple-git': {simpleGit: simpleGitStub},
        }).gitTag;

        try {
            await gitTagProxy();
        } catch (error:any) {
            expect(error.message).to.equal('some other error');
            expect(stepErrorStub.calledWith('git push origin tag 225_07_24 failed')).to.be.true;
        }
    })
})